/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package aptech.eproject.logictics.dao.an;

import javax.ejb.*;
import javax.persistence.*;
import java.util.List;
import javax.annotation.*;
import aptech.eproject.logictics.db.*;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;

/**
 *
 * @author AN
 */
@Stateless(name = "stateless/BookingHistoryManage")
@TransactionManagement(value = TransactionManagementType.CONTAINER)
public class BookingHistoryManage implements BookingHistoryManageRemote {

    @Resource
    private SessionContext context;
    @PersistenceContext(name = "LogicticsService")
    EntityManager em;

    /**
     * Get booked delivery of customer
     * @param username
     *  username of customer
     * @return
     *  list of deliveries of that customer
     */
    public List getDeliveryList(String username) {
        Query query = em.createQuery("SELECT d FROM Delivery d WHERE d.isDeleted='false' AND d.consigner.userName=?1");
        query.setParameter("1", username);
        return query.getResultList();
    }

    /**
     * Calculate cancellation fee when customer cancel a delivery
     * @param d
     *  Delivery entity
     * @return
     *  cancellation fee
     */
    public double calculateCancellationFee(Delivery d) {
        if (d.getConfirmedDate() == null) {
            return 0;
        }
        Calendar now = Calendar.getInstance();
        long mil = 24 * 3600 * 1000;
        double days = ((double) now.getTimeInMillis() - d.getConfirmedDate().getTime()) / mil;
        double percent = 5;
        if (days <= 1) {
            //cancel within 1 day
            percent = 5;
        } else if (days <= 2) {
            //cancel within 2 days
            percent = 10;
        } else {
            //cancel in more than 2 days
            percent = 15;
        }
        double fee = percent / 100 * d.getRate().doubleValue();
        return fee;
    }

    /**
     *  Update booking status of delivery
     * @param deliveryID
     *  deliveryID
     * @param bookingStatus
     *  new booking status of delivery
     * @return
     *  true: update successfully
     *  false: failed to update
     */
    public boolean updateBookingStatus(int deliveryID, BookingStatus bookingStatus) {
        try {
            Delivery d = em.find(Delivery.class, deliveryID);
            if (bookingStatus == BookingStatus.Canceled && d.getBookingStatus() == BookingStatus.Confirmed) {
                double cancelFee = calculateCancellationFee(d);
                d.setPubnishRate(new BigDecimal(cancelFee));
            }
            if (bookingStatus == BookingStatus.Confirmed) {
                Date dNow = new Date();
                Timestamp now = new Timestamp(dNow.getTime());
                d.setConfirmedDate(now);
            }
            d.setBookingStatus(bookingStatus);
            em.merge(d);
            return true;
        } catch (NullPointerException ex) {
            //System.err.println("Cannot find entity....");
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Get Delivery entity by its ID
     * @param deliveryID
     *  ID of delivery
     * @return
     *  Delivery entity
     */
    public Delivery getDeliveryByID(int deliveryID) {
        try {
            Delivery d = em.find(Delivery.class, deliveryID);
            return d;
        } catch (NullPointerException ex) {
            //System.err.println("Cannot find entity....");
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
